package com.neusoft.orcode.Utils;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.engines.RSAEngine;
import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jcajce.provider.asymmetric.rsa.KeyPairGeneratorSpi;
//import org.bouncycastle.util.encoders.Base64;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Optional;

@Slf4j
public class RSAUtil {

    static String privateKeyString = "";
    static String publicKeyString = "";

    private RSAUtil() {
    }

    // 生成
    public static void generate() {
        KeyPairGeneratorSpi keyPairGeneratorSpi = new KeyPairGeneratorSpi();
        keyPairGeneratorSpi.initialize(2048, new SecureRandom());//512 8的倍数
        KeyPair pair = keyPairGeneratorSpi.generateKeyPair();
        // 生成公钥和私钥
        PrivateKey privateKey = pair.getPrivate();
        PublicKey publicKey = pair.getPublic();
        byte[] privateKeyEncoded = privateKey.getEncoded();
        byte[] publicKeyEncoded = publicKey.getEncoded();
        privateKeyString = Base64.encode(privateKeyEncoded);
        publicKeyString = Base64.encode(publicKeyEncoded);
        // 输出公钥和私钥
        System.out.println("公钥:\n" + publicKeyString);
        System.out.println("私钥:\n" + privateKeyString);
    }

    // 加密
    public static Optional<String> encrypt(String publicKey, String content) {
        try {
            RSAEngine engine = new RSAEngine();
            // true表示加密
            engine.init(true, PublicKeyFactory.createKey(Base64.decode(publicKey)));
//            byte[] contentByte = content.getBytes(StandardCharsets.UTF_8);\
            System.out.println(content);// 正常
            byte[] contentByte = Base64.decode(content);
            System.out.println(contentByte);
            byte[] bytes = engine.processBlock(contentByte, 0, contentByte.length);
            return Optional.of(Base64.encode(bytes));
        } catch (Exception e) {
            log.error("加密异常!{}", e.getMessage());
        }
        return Optional.empty();
    }

    // 解密
    public static Optional<String> decrypt(String privateKey, String content) {
        try {
            RSAEngine engine = new RSAEngine();
            // false表示解密
            engine.init(false, PrivateKeyFactory.createKey(Base64.decode(privateKey)));
            byte[] contentByte = Base64.decode(content);
            byte[] bytes = engine.processBlock(contentByte, 0, contentByte.length);
            return Optional.of(new String(bytes, StandardCharsets.UTF_8));
        } catch (Exception e) {
            log.error("解密异常!{}", e.getMessage());
        }
        return Optional.empty();
    }


    public static void main(String[] args) {
        generate();
        System.out.println("加密:");
        encrypt(publicKeyString, "hello word").ifPresent(content -> {
            System.out.println(content);
            System.out.println("解密:");
            decrypt(privateKeyString, content).ifPresent(System.out::println);
        });
        //非lambda表达式 
        Optional<String> helloWord = encrypt(publicKeyString, "hello word");
        if (helloWord.isPresent()) {
            String content = helloWord.get();
            System.out.println(content);
            System.out.println("解密:");
            decrypt(privateKeyString, content).ifPresent(System.out::println);
        }


    }
}